﻿using System;
using System.Linq;
using System.Threading.Tasks;
using HtmlAgilityPack;
using YGBookmark.Utils;
using HtmlDocument = HtmlAgilityPack.HtmlDocument;
namespace YGBookmark.Services
{
    /// <summary>
    /// 网页内容分析服务（支持元数据提取和智能降级策略）
    /// </summary>
    public class WebAnalyzer
    {
        #region 配置常量
        private const int MaxSummaryLength = 300;       // 摘要最大长度
        private const int MinImageSize = 100;           // 最小图片尺寸
        private const int AnalysisTimeout = 20;         // 分析超时秒数
        private static readonly string[] IgnoreImgExtensions = { "svg", "ico" }; // 忽略图片类型
        #endregion

        /// <summary>
        /// 分析网页内容（支持重试机制）
        /// </summary>
        public async Task<WebPageAnalysisResult> AnalyzeAsync(string url)
        {
            using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(AnalysisTimeout));
            for (int retry = 0; retry < 3; retry++)
            {
                try
                {
                    var html = await HttpHelper.GetHtmlContentAsync(url);
                    return ParseHtml(html, url);
                }
                catch (Exception ex) when (retry < 2 && IsRetryableError(ex))
                {
                    await Task.Delay(1000 * (retry + 1), timeoutCts.Token);
                }
            }
            throw new WebAnalysisException($"无法解析网页内容: {url}");
        }

        #region 核心解析逻辑
        private WebPageAnalysisResult ParseHtml(string html, string baseUrl)
        {
            var doc = new HtmlDocument();
            doc.LoadHtml(html);

            return new WebPageAnalysisResult
            {
                Title = GetTitle(doc),
                CoverImage = GetCoverImage(doc, baseUrl),
                Summary = GetSummary(doc),
                RawHtml = html
            };
        }

        private string GetTitle(HtmlDocument doc)
        {
            // 优先从Open Graph获取标题
            var ogTitle = doc.DocumentNode.SelectSingleNode("//meta[@property='og:title']")?
                .GetAttributeValue("content", null);

            // 回退到常规标题标签
            return ogTitle ?? doc.DocumentNode.SelectSingleNode("//title")?.InnerText.Trim()
                ?? "无标题";
        }

        private string GetCoverImage(HtmlDocument doc, string baseUrl)
        {
            // Open Graph图片
            var ogImage = doc.DocumentNode.SelectSingleNode("//meta[@property='og:image']")?
                .GetAttributeValue("content", null);
            if (!string.IsNullOrEmpty(ogImage))
                return MakeAbsoluteUrl(ogImage, baseUrl);

            // Twitter卡片图片
            var twitterImage = doc.DocumentNode.SelectSingleNode("//meta[@name='twitter:image']")?
                .GetAttributeValue("content", null);
            if (!string.IsNullOrEmpty(twitterImage))
                return MakeAbsoluteUrl(twitterImage, baseUrl);

            // 在主体内容中查找第一个合适图片
            var firstContentImage = doc.DocumentNode
                .Descendants("img")
                .Where(IsValidImage)
                .Select(img => img.GetAttributeValue("src", null))
                .FirstOrDefault();

            return firstContentImage != null
                ? MakeAbsoluteUrl(firstContentImage, baseUrl)
                : string.Empty;
        }

        private string GetSummary(HtmlDocument doc)
        {
            // 优先获取Open Graph描述
            var ogDescription = doc.DocumentNode
                .SelectSingleNode("//meta[@property='og:description']")?
                .GetAttributeValue("content", null);

            if (!string.IsNullOrWhiteSpace(ogDescription))
                return TruncateSummary(ogDescription);

            // 获取常规meta描述
            var metaDescription = doc.DocumentNode
                .SelectSingleNode("//meta[@name='description']")?
                .GetAttributeValue("content", null);

            if (!string.IsNullOrWhiteSpace(metaDescription))
                return TruncateSummary(metaDescription);

            // 回退到正文内容提取
            var textNodes = doc.DocumentNode.SelectNodes("//body//text()[not(parent::script)]");
            if (textNodes == null) return string.Empty;

            var fullText = string.Join(" ", textNodes
                .Select(n => n.InnerText.Trim())
                .Where(t => !string.IsNullOrWhiteSpace(t)));

            return TruncateSummary(fullText);
        }
        #endregion

        #region 辅助方法
        private bool IsRetryableError(Exception ex)
        {
            return ex is HttpRequestException ||
                   ex is TimeoutException ||
                   ex is TaskCanceledException;
        }

        private bool IsValidImage(HtmlNode imgNode)
        {
            // 排除图标类图片
            var src = (imgNode.GetAttributeValue("src", "") ?? "").ToLower();
            if (IgnoreImgExtensions.Any(ext => src.EndsWith($".{ext}")))
                return false;

            // 检查图片尺寸
            var width = GetNumericAttribute(imgNode, "width");
            var height = GetNumericAttribute(imgNode, "height");
            return Math.Max(width, height) >= MinImageSize;
        }

        private int GetNumericAttribute(HtmlNode node, string attrName)
        {
            var value = node.GetAttributeValue(attrName, "0");
            return int.TryParse(value, out int num)
                ? num
                : 0;
        }

        private string TruncateSummary(string text)
        {
            text = text.Trim();
            return text.Length > MaxSummaryLength
                ? text.Substring(0, MaxSummaryLength) + "..."
                : text;
        }

        private string MakeAbsoluteUrl(string url, string baseUrl)
        {
            try
            {
                if (Uri.IsWellFormedUriString(url, UriKind.Absolute))
                    return url;

                var baseUri = new Uri(baseUrl);
                return new Uri(baseUri, url).AbsoluteUri;
            }
            catch
            {
                return url;
            }
        }
        #endregion

        #region 结果模型
        public class WebPageAnalysisResult
        {
            public string Title { get; set; }       // 网页标题
            public string CoverImage { get; set; }  // 封面URL
            public string Summary { get; set; }     // 内容摘要
            public string RawHtml { get; set; }     // 原始HTML（可选）
        }
        #endregion

        #region 自定义异常
        public class WebAnalysisException : Exception
        {
            public WebAnalysisException(string message) : base(message) { }
            public WebAnalysisException(string message, Exception inner)
                : base(message, inner) { }
        }
        #endregion
    }
}